#ifndef _FSNOTIFY_IMP_H
#define _FSNOTIFY_IMP_H

#define G_LOG_DOMAIN "fsnotify"

#include <syncupconfig.h>
#include <fsnotify.h>
#include <pthread.h>

struct fsnotify {
    struct fsnotify_desc desc;
    GHashTable *inode_map;
    struct dentry *root;
    struct list_head evt_queue;
    struct list_head evt_hdlr_list;
    pthread_mutex_t evt_hdlr_mutex;
    pthread_t tid;
};

extern struct fsnotify fsnotify;

extern int fsnotify_desc_open(struct fsnotify_desc *desc);
extern void fsnotify_desc_close(struct fsnotify_desc *desc);

static inline struct fsnotify_event *
fsnotify_event_new(uint32_t mask)
{
    struct fsnotify_event *fs_evt = g_slice_new(struct fsnotify_event);
    fs_evt->mask = mask;
    fs_evt->name = NULL;
    fs_evt->new_name = NULL;
    fs_evt->garbage = NULL;
    return fs_evt;
}

static inline void
fsnotify_event_free(struct fsnotify_event *evt)
{
    if (evt->name) {
        free(evt->name);
    }
    if (evt->new_name) {
        free(evt->new_name);
    }
    if (evt->garbage) {
        dentry_free(evt->garbage);
    }
    g_slice_free(struct fsnotify_event, evt);
}

static inline void
fsnotify_event_set_name(struct fsnotify_event *evt, const char *name)
{
    evt->name = strdup(name);
}

static inline void
fsnotify_event_set_new_name(struct fsnotify_event *evt, const char *name)
{
    evt->new_name = strdup(name);
}

/**
 * @brief Read events as \c fsnotify_event into a queue
 * @return 0 if success and -1 on error
 * @note NOT thread-safe
 */
extern int fsnotify_read_event(struct fsnotify_desc *desc, struct list_head *evt_queue);

#ifdef OS_WIN
extern void fsnotify_cancel_read_event();
#endif

#endif /* ! _FSNOTIFY_IMP_H */
